<template>
  <div class="progress-container" :style="containerStyle">
    <div class="progress-bar" :style="progressBarStyle"></div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'

// 定义 props
const props = defineProps({
  // 进度值 (0-100)
  progress: {
    type: Number,
    required: true,
    validator: (value: number) => value >= 0 && value <= 100,
  },
  // 颜色配置，可以是字符串或颜色停止点数组
  color: {
    type: [String, Array] as () => string | Array<{ progress: number; color: string }>,
    default: '#4CAF50',
  },
  // 过渡动画时间 (ms)
  transitionDuration: {
    type: Number,
    default: 300,
  },
  // 颜色过渡时间 (ms)
  colorTransitionDuration: {
    type: Number,
    default: 500,
  },
  // 容器高度
  height: {
    type: [String, Number],
    default: '8px',
  },
  // 容器背景色
  containerBgColor: {
    type: String,
    default: '#e0e0e0',
  },
  // 圆角半径
  borderRadius: {
    type: [String, Number],
    default: '4px',
  },
  // 是否显示条纹
  striped: {
    type: Boolean,
    default: false,
  },
  // 是否启用条纹动画
  animated: {
    type: Boolean,
    default: false,
  },
})

// 当前进度 (用于动画)
const computedProgress = ref(0)
// 当前颜色
const currentColor = ref('#4CAF50')

/**
 * 标准化颜色配置
 * @param color 颜色配置 (字符串或数组)
 * @returns 标准化后的颜色停止点数组
 */
const normalizeColorConfig = (
  color: string | Array<{ progress: number; color: string }>,
): Array<{ progress: number; color: string }> => {
  // 如果是字符串，转换为单元素的数组
  if (typeof color === 'string') {
    return [{ progress: 0, color }]
  }

  // 如果是数组但为空，返回默认颜色
  if (Array.isArray(color) && color.length === 0) {
    return [{ progress: 0, color: '#4CAF50' }]
  }

  // 如果是有效数组，返回排序后的副本
  if (Array.isArray(color)) {
    return [...color].sort((a, b) => a.progress - b.progress)
  }

  // 其他情况返回默认
  return [{ progress: 0, color: '#4CAF50' }]
}

/**
 * 计算当前进度对应的颜色
 * @param progress 当前进度 (0-100)
 * @param colors 颜色配置数组
 * @returns 计算出的颜色值
 */
const calculateProgressColor = (
  progress: number,
  colors: Array<{ progress: number; color: string }>,
): string => {
  // 如果只有一个颜色停止点，直接返回该颜色
  if (colors.length === 1) {
    return colors[0].color
  }

  // 如果进度小于第一个停止点，返回第一个颜色
  if (progress <= colors[0].progress) {
    return colors[0].color
  }

  // 如果进度大于最后一个停止点，返回最后一个颜色
  if (progress >= colors[colors.length - 1].progress) {
    return colors[colors.length - 1].color
  }

  // 查找当前进度所在的区间
  for (let i = 0; i < colors.length - 1; i++) {
    if (progress >= colors[i].progress && progress <= colors[i + 1].progress) {
      const range = colors[i + 1].progress - colors[i].progress
      const ratio = (progress - colors[i].progress) / range
      return interpolateColor(colors[i].color, colors[i + 1].color, ratio)
    }
  }

  // 默认返回最后一个颜色
  return colors[colors.length - 1].color
}

/**
 * 颜色插值计算 (HEX格式)
 * @param color1 起始颜色
 * @param color2 结束颜色
 * @param ratio 混合比例 (0-1)
 * @returns 插值后的颜色
 */
const interpolateColor = (color1: string, color2: string, ratio: number): string => {
  // 解析HEX颜色
  const r1 = parseInt(color1.substring(1, 3), 16)
  const g1 = parseInt(color1.substring(3, 5), 16)
  const b1 = parseInt(color1.substring(5, 7), 16)

  const r2 = parseInt(color2.substring(1, 3), 16)
  const g2 = parseInt(color2.substring(3, 5), 16)
  const b2 = parseInt(color2.substring(5, 7), 16)

  // 计算插值
  const r = Math.round(r1 + (r2 - r1) * ratio)
  const g = Math.round(g1 + (g2 - g1) * ratio)
  const b = Math.round(b1 + (b2 - b1) * ratio)

  // 转回HEX格式
  return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`
}

// 容器样式
const containerStyle = computed(() => ({
  height: typeof props.height === 'number' ? `${props.height}px` : props.height,
  backgroundColor: props.containerBgColor,
  borderRadius:
    typeof props.borderRadius === 'number' ? `${props.borderRadius}px` : props.borderRadius,
}))

// 进度条样式
const progressBarStyle = computed(() => {
  const baseStyle: Record<string, string> = {
    width: `${computedProgress.value}%`,
    backgroundColor: currentColor.value,
    transition: `width ${props.transitionDuration}ms ease, background-color ${props.colorTransitionDuration}ms ease`,
    height: '100%',
  }

  // 条纹效果
  if (props.striped) {
    baseStyle.backgroundImage = `linear-gradient(
      45deg,
      rgba(255, 255, 255, 0.15) 25%,
      transparent 25%,
      transparent 50%,
      rgba(255, 255, 255, 0.15) 50%,
      rgba(255, 255, 255, 0.15) 75%,
      transparent 75%,
      transparent
    )`
    baseStyle.backgroundSize = '1rem 1rem'
  }

  // 条纹动画
  if (props.animated && props.striped) {
    baseStyle.animation = 'progress-bar-stripes 1s linear infinite'
  }

  return baseStyle
})

// 监听进度变化
watch(
  () => props.progress,
  (newVal) => {
    computedProgress.value = newVal
    // 每次进度变化时重新计算颜色
    const normalizedColors = normalizeColorConfig(props.color)
    currentColor.value = calculateProgressColor(newVal, normalizedColors)
  },
)

// 初始化
onMounted(() => {
  computedProgress.value = props.progress
  const normalizedColors = normalizeColorConfig(props.color)
  currentColor.value = calculateProgressColor(props.progress, normalizedColors)
})
</script>

<style scoped>
.progress-container {
  position: relative;
  width: 100%;
  overflow: hidden;
}

.progress-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0%;
}

@keyframes progress-bar-stripes {
  0% {
    background-position-x: 1rem;
  }
}
</style>
